package com.es.demo.high.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.es.demo.document.ProductInfo;
import com.es.demo.high.service.ProductHighService;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.elasticsearch.action.DocWriteRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class ProductHighServiceImpl implements ProductHighService {

    @Autowired
    private RestHighLevelClient restHighLevelClient;

    @Override
    public Boolean save(ProductInfo... productInfo) {
//        IndexRequest request = new IndexRequest();
//        for (ProductInfo info : productInfo) {
//            request.index("product-info").id(String.valueOf(info.getId()));
//            request.source(XContentType.JSON, info);
//            try {
//                IndexResponse response = restHighLevelClient.index(request, RequestOptions.DEFAULT);
//                // 打印结果信息
//                System.out.println("_index: " + response.getIndex());
//                System.out.println("id: " + response.getId());
//                System.out.println("_result: " + response.getResult());
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//        }
        //循环插入/更新
//        UpdateRequest updateRequest = new UpdateRequest();
//        for (ProductInfo info : productInfo) {
//            updateRequest.index("product-info").id(String.valueOf(info.getId()));
//            updateRequest.doc(XContentType.JSON, info);
//            try {
//                UpdateResponse response = restHighLevelClient.update(updateRequest, RequestOptions.DEFAULT);
//                // 打印结果信息
//                System.out.println("_index: " + response.getIndex());
//                System.out.println("id: " + response.getId());
//                System.out.println("_result: " + response.getResult());
//            } catch (IOException e) {
//                throw new RuntimeException(e);
//            }
//        }

        //批量操作estHighLevelClient.bulk()可以包含新增，修改，删除
        BulkRequest request = new BulkRequest();
        Arrays.stream(productInfo).forEach(info -> {
            IndexRequest indexRequest = new IndexRequest();
            indexRequest.index("product-info").id(String.valueOf(info.getId()));
            try {
                //通过ObjectMapper将对象转成字符串再保存，如果不转的话存入的格式不是正常的json格式数据，不能转成对象
                ObjectMapper objectMapper = new ObjectMapper();
                String productJson = objectMapper.writeValueAsString(info);
                indexRequest.source(productJson, XContentType.JSON);
            } catch (JsonProcessingException e) {
                throw new RuntimeException(e);
            }
            request.add(indexRequest);
        });
        try {
            BulkResponse response = restHighLevelClient.bulk(request, RequestOptions.DEFAULT);
            System.out.println(response.status().getStatus());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    @Override
    public Boolean delete(Integer id) {
        DeleteRequest deleteRequest = new DeleteRequest().index("product-info").id(String.valueOf(id));
        try {
            DeleteResponse response = restHighLevelClient.delete(deleteRequest, RequestOptions.DEFAULT);
            // 打印结果信息
            System.out.println("_index: " + response.getIndex());
            System.out.println("_id: " + response.getId());
            System.out.println("result: " + response.getResult());
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    @Override
    public ProductInfo getById(Integer id) {
        GetRequest getRequest = new GetRequest().index("product-info").id(String.valueOf(id));
        try {
            GetResponse response = restHighLevelClient.get(getRequest, RequestOptions.DEFAULT);
            // 打印结果信息
            System.out.println("_index: " + response.getIndex());
            System.out.println("_type: " + response.getType());
            System.out.println("_id: " + response.getId());
            System.out.println("source: " + response.getSourceAsString());
            if (StringUtils.hasLength(response.getSourceAsString())) {
                return JSONObject.parseObject(response.getSourceAsString(), ProductInfo.class);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return null;
    }

    @Override
    public List<ProductInfo> getAll() {
        SearchRequest request = new SearchRequest();
        request.indices("product-info");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchAllQuery());
        //restHighLevelClient在执行默认查询时返回条数都是10条，查询所有的时候要设置上size
        //lasticsearch exception [type=illegal_argument_exception, reason=Result window is too large, from + size must be less than or equal to: [10000] but was [1000000]
        //size不能设置查过10000条，
        searchSourceBuilder.size(1000);
        request.source(searchSourceBuilder);
        List<ProductInfo> result = new ArrayList<>();
        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            response.getHits().forEach(e -> {
                ProductInfo productInfo = JSONObject.parseObject(e.getSourceAsString(), ProductInfo.class);
                result.add(productInfo);
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return result;
    }

    @Override
    public List<ProductInfo> query(String keyword) {
        //https://blog.csdn.net/qq_38826019/article/details/121344376
        SearchRequest request = new SearchRequest();
        request.indices("product-info");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(QueryBuilders.matchQuery("productName", keyword));
        searchSourceBuilder.query(QueryBuilders.matchQuery("description", keyword));
        //分页
//        searchSourceBuilder.from();
//        searchSourceBuilder.size()
        request.source(searchSourceBuilder);
        List<ProductInfo> result = new ArrayList<>();
        try {
            SearchResponse response = restHighLevelClient.search(request, RequestOptions.DEFAULT);
            response.getHits().forEach(e -> {
                ProductInfo productInfo = JSONObject.parseObject(e.getSourceAsString(), ProductInfo.class);
                result.add(productInfo);
            });
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return result;
    }
}
